﻿#region Using directives
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Web.Script.Services;
using System.Web.Services;

#endregion

namespace ProcolServices {
    /// <summary>
    /// Summary description for ProjectsService
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [ToolboxItem(false)]
    [ScriptService]
    public class ProjectService : WebService {
        private readonly ProcolDataContext db = new ProcolDataContext();

        [WebMethod]
        public ProjectBean[] GetListOfProjectsByKeyword(String keyword) {
            var list = new List<ProjectBean>();
            var query = from i in db.Projects
                        where i.Name.Contains(keyword) || i.Tags.Contains(keyword)
                        orderby i.DateCreated descending
                        select new {i.ProjectId, i.UserId, i.Name, i.Description, i.Status,
                            i.Rating, i.Name.Length, i.DateCreated, i.Category};

            foreach (var q in query) {
                if (q.Status != 0)
                {
                    list.Add(new ProjectBean
                    {
                        projectId = q.ProjectId,
                        userId = q.UserId,
                        description = q.Description.Trim(),
                        name = q.Name.Trim(),
                        rating = q.Rating,
                        status = q.Status,
                        nameLength = q.Length,
                        dateCreated = q.DateCreated,
                        category = q.Category,
                        statusText = ""
                    });
                }
            }

            return list.ToArray();
        }

        [WebMethod]
        public ProjectBean[] GetListOfProjectsByUserId(int userId)
        {
            var list = new List<ProjectBean>();
            var query = from i in db.Projects
                        where i.UserId == userId
                        select new { i.ProjectId, i.UserId, i.Name, i.Description, i.Status,
                            i.Rating, i.Name.Length, i.DateCreated, i.Category };

            foreach (var q in query)
            {
                list.Add(new ProjectBean
                {
                    projectId = q.ProjectId,
                    userId = q.UserId,
                    description = q.Description.Trim(),
                    name = q.Name.Trim(),
                    rating = q.Rating,
                    status = q.Status,
                    nameLength = q.Length,
                    dateCreated = q.DateCreated,
                    category = q.Category
                });
            }

            return list.ToArray();
        }

        [WebMethod]
        public String[] GetListOfProjectsNames(String keyword, int count)
        {
            var query = from i in db.Projects
                        where i.Name.Contains(keyword) || i.Tags.Contains(keyword)
                        select String.Join(" ", new[] {i.Name});

            return query.Take(10).ToArray();
        }

        [WebMethod]
        public ProjectCommentBean[] GetListOfProjectsComments(int projectId)
        {
            UserService userService = new UserService();
            var list = new List<ProjectCommentBean>();
            var query = from i in db.ProjectComments
                        where i.ProjectId == projectId
                        orderby i.DateCreated descending
                        select i;

            foreach (var q in query)
            {
                list.Add(new ProjectCommentBean
                {
                    commentId = q.CommentId,
                    projectId = q.ProjectId,
                    userId = q.UserId,
                    title = q.Title,
                    comment = q.Comment,
                    dateCreated = q.DateCreated,
                    creatorName = userService.GetUserName(q.UserId)
                });
            }

            return list.ToArray();
        }

        [WebMethod]
        public int GetNumberOfProjects(int userId)
        {
            var query = (from i in db.Projects
                        where i.UserId == userId
                        select i).Count();

            return query;
        }

        [WebMethod]
        public ProjectBean GetProject(int projectId)
        {
            var query = from i in db.Projects
                        where i.ProjectId == projectId
                        select new { i.ProjectId, i.UserId, i.Name, i.Description, i.Status,
                            i.Rating, i.Name.Length, i.DateCreated, i.Category, i.Tags, i.TutorId,};
            ProjectBean result = new ProjectBean();
            foreach (var q in query)
            {
                var subQuery = from i in db.Projects
                            join o in db.Users on i.UserId equals o.UserId
                            where i.ProjectId == projectId
                            select new { o.Name, o.LastnameD, o.LastnameM };
                result = new ProjectBean
                  {
                      projectId = q.ProjectId,
                      userId = q.UserId,
                      description = q.Description.Trim(),
                      name = q.Name.Trim(),
                      rating = q.Rating,
                      status = q.Status,
                      nameLength = q.Length,
                      dateCreated = q.DateCreated,
                      category = q.Category,
                      ownersName = subQuery.ToArray()[0].Name + " " +
                        subQuery.ToArray()[0].LastnameD + " " +
                        subQuery.ToArray()[0].LastnameM,
                      tags = q.Tags,
                      tutorId = q.TutorId,
                      statusText = ""
                  };
            }
            return result;
        }

        [WebMethod]
        public String GetProjectName(int projectId)
        {
            try
            {
                var query = (from i in db.Projects
                             where i.ProjectId == projectId
                             select i.Name).Single();
                return query;
            }
            catch (InvalidOperationException)
            {
                return null;
            }
        }

        [WebMethod]
        public bool isOwner(int userId, int projectId)
        {
            try
            {
                var query = (from i in db.Projects
                             where i.ProjectId == projectId
                             select i.UserId).Single();
                if (query == userId)
                    return true;
                else
                    return false;
            }
            catch (InvalidOperationException)
            {
                return false;
            }
        }

        [WebMethod]
        public ProjectTagBean[] getProjectTags()
        {
            var list = new List<ProjectTagBean>();
            var query = from i in db.ProjectsTags
                        orderby i.number descending
                        select i;
            foreach (var q in query)
            {
                 list.Add(new ProjectTagBean
                 {
                     idTag = q.idTag,
                     text = q.text,
                     number = q.number
                 });
            }
            return list.ToArray();
        }

        [WebMethod]
        public ProjectBean[] searchForTag(int idTag)
        {
            try
            {
                String tagName = (from u in db.ProjectsTags
                                  where u.idTag == idTag
                                  select u.text).Single().Trim();
                var list = new List<ProjectBean>();
                var query = from i in db.Projects
                            where i.Tags.Contains(tagName)
                            select i;
                foreach (var q in query)
                {
                    list.Add(new ProjectBean
                    {
                        projectId = q.ProjectId,
                        name = q.Name.Trim(),
                        dateCreated = q.DateCreated
                    });
                }
                return list.ToArray();
            }
            catch (InvalidOperationException)
            {
                return null;
            }
        }

        [WebMethod]
        public String getTagName(int idTag)
        {
            try
            {
                var query = (from i in db.ProjectsTags
                            where i.idTag == idTag
                            select i.text).Single();
                return query;
            }
            catch (InvalidOperationException)
            {
                return null;
            }
        }

        [WebMethod]
        public int AddNewProject(int projectId, String projectName, byte projectStatus, float projectRate,
                                 DateTime dateCreation) {
            var values = new Object[] {projectId, projectName, projectStatus, projectRate, dateCreation};
            foreach (var value in values) {
                String str = value.ToString();
                int tryParse;

                if (Int32.TryParse(str, out tryParse)) {
                    if (tryParse < 0)
                        return -2;
                } else if (String.IsNullOrEmpty(str))
                    return -2;
            }
            try {
                var newProject = new Project {
                        ProjectId = projectId,
                        Name = projectName,
                        Status = projectStatus,
                        Rating = projectRate,
                        DateCreated = dateCreation,
                };
                db.Projects.InsertOnSubmit(newProject);
                db.SubmitChanges();

                return newProject.ProjectId;
            } catch (InvalidOperationException) {
                return -2;
            }
        }

        [WebMethod]
        // return 1 if the project is logically deleted
        // return -1 if occurs and error while deleting
        // return -2 if the parameter is null
        public int LogicDeleteProject(int projectId) {
            var values = new object[] { projectId };

            // Check for null/default values (x < 0 or empty string -> "")
            foreach (var value in values) {
                String str = value.ToString();
                int tryParse;

                if (Int32.TryParse(str, out tryParse)) {
                    if (tryParse < 0)
                        return -2;
                }
                else if (String.IsNullOrEmpty(str))
                    return -2;
            }
    
            try {
                /*User userQuery = (from u in db.Users
                                  where u.Username == username
                                  select u).Single();
                int userId = userQuery.UserId;*/
                //&& i.UserId == userId

                Project projectQuery = (from i in db.Projects
                                  where i.ProjectId == projectId
                                  select i).Single();
                projectQuery.Status = 0;
                db.SubmitChanges();
                return 0;
            }
            catch (InvalidOperationException) {
                return -1;
            }
        }

        [WebMethod]
        // Return 1 when updated
        public int UpdateProjectRecord(int projectId, String desProject, String projectName, String categoryProject, String projectTags) {
            var values = new object[] { projectId, desProject, projectName, categoryProject, projectTags };
            // Check for null/default values (x < 0 or empty string -> "")
            foreach (var value in values) {
                String str = value.ToString();
                int tryParse;

                if (Int32.TryParse(str, out tryParse)) {
                    if (tryParse < 0)
                        return -2;
                }
                else if (String.IsNullOrEmpty(str))
                        return -2;
            }

            try {
                Project projectQuery = (from i in db.Projects
                                  where i.ProjectId == projectId
                                  select i).Single();
                projectQuery.Description = desProject;
                projectQuery.Name = projectName;
                projectQuery.Category = categoryProject;
                projectQuery.Tags = projectTags;
                db.SubmitChanges();
                return 1;
            }
            catch (InvalidOperationException) {
                return -1;
            }
        }

        #region Nested type: ProjectBean
        public class ProjectBean {
            public int projectId { get; set; }
            public int userId { get; set; }
            public String name { get; set; }
            public String description { get; set; }
            public int status { get; set; }
            public double rating { get; set; }
            public int nameLength { get; set; }
            public System.DateTime dateCreated { get; set; }
            public String category { get; set; }
            public String ownersName { get; set; }
            public String tags { get; set; }
            public int tutorId { get; set; }
            public String statusText { get; set; }
            public int teamId { get; set; }
        }
        #endregion

        #region Nested type: ProjectCommentBean
        public class ProjectCommentBean
        {
            public int commentId { get; set; }
            public int userId { get; set; }
            public int projectId { get; set; }
            public String title { get; set; }
            public String comment { get; set; }
            public DateTime dateCreated { get; set; }
            public String creatorName { get; set; }
        }
        #endregion

        #region Nested type: ProjectTagBean
        public class ProjectTagBean
        {
            public int idTag { get; set; }
            public String text { get; set; }
            public int number { get; set; }
        }
        #endregion

    }
}